package tool;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * ����Ч��
 * http://www.woshipm.com/pd/595757.html
 * �ܴa���Ҫ��8��Ԫ
 * ���ٷ���������������Ҏ�t:
 * ��Ӣ����Ԫ
 * С��Ӣ����Ԫ
 * ������Ԫ
 * ��̖��Ԫ
 * <p>
 * ������Ԫ��׃������߷֔�.
 * ����ķ֔���ӷ��Ŀ�͜p���Ŀ�Ŀ���.
 * �֔��Ĺ�����0~100��.
 * �֔������_�������Ԫ����Ӌ��.
 * <p>
 * �ӷ���Ŀ
 * ��������/Flat/+(n*4)
 * ��дӢ����ĸ/Cond��Incr/+((len-n)*2)
 * СдӢ����ĸ/Cond��Incr/+((len-n)*2)
 * ������Ԫ/Cond/+(n*4)
 * ������Ԫ/Flat/+(n*6)
 * �����м䴩�����ֻ������Ԫ/Flat/+(n*2)
 * �Ѵﵽ�������Ҫ����Ŀ/Flat/+(n*2)
 * �۷���Ŀ
 * ֻ��Ӣ����Ԫ/Flat/-n
 * ֻ��������Ԫ/Flat/-n
 * �ظ���Ԫ(Case Insensitive)/Incr/-(n(n-1))
 * ����Ӣ�Ĵ�д��Ԫ/Flat/-(n*2)
 * ����Ӣ��Сд��Ԫ/Flat/-(n*2)
 * ����������Ԫ/Flat/-(n*2)
 * ������ĸ��������(��abc, def)/Flat/-(n*3)
 * �������ֳ�������(��123,234)/Flat/-(n*3)
 * <p>
 * �ο�����:
 * https://blog.csdn.net/u010156024/article/details/45673581
 */
public class CheckPassword {
    private String password;
    private int length;//���볤��
    private int upperAlp = 0;//��д��ĸ����
    private int lowerAlp = 0;//Сд��ĸ����
    private int num = 0;//���ֳ���
    private int charlen = 0;//�����ַ�����
    private int score = 0;//����


    public CheckPassword(String password) {
        this.password = password.replaceAll("\\s", "");
        this.length = password.length();
        System.out.println(this.password);

        ExtraPoints();
        System.out.println("-------------------------");
        MinusPoint();
        System.out.println(score + "\t" + (score!=100?(score / 20 + 1):5));
    }

    //���볤�Ȼ���    n*4
    public int CheckpasswordLength() {
        if (this.length >= 8) {
            score += 8 * 4;
            return 8 * 4;
        } else {
            score += this.length * 4;
            return this.length * 4;
        }
    }

    //��д��ĸ����    (len-n)x2
    public int CheckpasswordUpper() {
        String reg = "[A-Z]";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(password);
        int j = 0;
        while (matcher.find()) {
            j++;
        }
        this.upperAlp = j;

        if (this.length -j > 8) {
            score += 8 * 2;
            return 8 * 2;
        } else {
            score += (this.length - j) * 2;
            return (this.length - j) * 2;
        }

    }

    //����Сд��ĸ��Ԫ  (len-n)x2
    public int CheckPwsLower() {
        String reg = "[a-z]";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(this.password);
        int j = 0;
        while (matcher.find()) {
            j++;
        }
        this.lowerAlp = j;
        if (this.length - j > 8) {
            score += 8 * 2;
            return 8 * 2;
        } else {
            score += (this.length - j) * 2;
            return (this.length - j) * 2;
        }
    }

    //����������Ԫ    n*4
    public int checkNum() {
        String reg = "[0-9]";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(this.password);
        int j = 0;
        while (matcher.find()) {
            j++;
        }
        this.num = j;
        if (j * 4 > 12) {
            score += 12;
            return 3 * 4;
        } else {
            score += j * 4;
            return j * 4;
        }
    }

    //���Է�����Ԫ    n*6
    public int checkChar() {
        charlen = this.length - this.upperAlp
                - this.lowerAlp - this.num;

        if (this.charlen * 6 > 12) {
            score += 12;
            return 6 * 2;
        } else {
            score += this.charlen * 6;
            return this.charlen * 6;
        }
    }

    //�ܴa���g���唵�ֻ��̖��Ԫ n*2
    public int checkNumOrCharInStr() {
        int j = this.num + this.charlen;
        if(j*2 >6){
            score += 3 * 2;
            return 3 * 2;
        }
        score += j * 2;
        return j * 2;
    }

    /**
     * ���Ҫ���׼
     * �÷�����Ҫ�����ϼӷַ���ʹ�ú�ſ���ʹ�� n*2
     *
     * @return
     */
    public int LowerQuest() {
        int j = 0;
        if (this.length >= 8) {
            j++;
        }
        if (this.upperAlp > 0) {
            j++;
        }
        if (this.lowerAlp > 0) {
            j++;
        }
        if (this.num > 0) {
            j++;
        }
        if (this.charlen > 0) {
            j++;
        }

        score += j * 2;
        return j * 2;
    }


    /**
     * =================�ָ���===�۷���Ŀ=====================
     **/
    //ֻ����Ӣ����ĸ   n
    public int OnlyHasAlp() {
        if (this.length == (this.upperAlp + this.lowerAlp)) {
            score += -this.length;
            return -this.length;
        }
        return 0;
    }

    //ֻ�������� n
    public int OnlyHasNum() {
        if (this.length == this.num) {
            score += -this.length;
            return -this.length;
        }
        return 0;
    }

    //�ظ���Ԫ�۷�    n(n-1)
    public int repeatDex() {
        char[] c = this.password.toCharArray();
        HashMap<Character, Integer> hashMap =
                new HashMap<Character, Integer>();
        for (int i = 0; i < c.length; i++) {
            if (hashMap.containsKey(c[i])) {
                hashMap.put(c[i], hashMap.get(c[i]) + 1);
            } else {
                hashMap.put(c[i], 1);
            }
        }
        int sum = 0;
        Iterator<Map.Entry<Character, Integer>> iterator =
                hashMap.entrySet().iterator();
        while (iterator.hasNext()) {
            int j = iterator.next().getValue();
            if (j > 0) {
                sum = sum + j * (j - 1);
            }
        }
        score += -sum;
        return -sum;
    }

    //����Ӣ�Ĵ�д��Ԫ  n*2
    public int seriseUpperAlp() {
        int j = 0;
        String reg = "[A-Z]";
        Pattern pattern = Pattern.compile(reg);
        char[] c = this.password.toCharArray();
        for (int i = 0; i < c.length - 1; i++) {
            if (pattern.matcher(c[i] + "").find()
                    && pattern.matcher(c[i + 1] + "").matches()) {
                j++;
            }
        }
        if (-2 * j <= -8) {
            score += -8;
            return -2 * 4;
        } else {
            score += -2 * j;
            return -2 * j;
        }
    }

    //����Ӣ��Сд��Ԫ  n*2
    public int seriseLowerAlp() {
        String reg = "[a-z]";
        int j = 0;
        Pattern pattern = Pattern.compile(reg);
        char[] c = this.password.toCharArray();
        for (int i = 0; i < c.length - 1; i++) {
            if (pattern.matcher(c[i] + "").find()
                    && pattern.matcher(c[i + 1] + "").matches()) {
                j++;
            }
        }
        if (-2 * j > 8) {
            score += -8;
            return -2 * 4;
        } else {
            score += -2 * j;
            return -2 * j;
        }
    }

    //����������Ԫ    n*2
    public int seriseNum() {
        String reg = "[0-9]";
        Pattern pattern = Pattern.compile(reg);
        char[] c = this.password.toCharArray();
        int j = 0;
        for (int i = 0; i < c.length - 1; i++) {
            if (pattern.matcher(c[i] + "").matches()
                    && pattern.matcher(c[i + 1] + "").matches()) {
                j++;
            }
        }
        if (-2 * j > 8) {
            score += -8;
            return -2 * 4;
        } else {
            score += -2 * j;
            return -2 * j;
        }
    }

    //������ĸabc def֮�೬��3���۷�  �����ִ�Сд��ĸ
    public int seriesAlp2Three() {
        int j = 0;
        char[] c = this.password.toLowerCase(Locale.CHINA).toCharArray();
        for (int i = 0; i < c.length - 2; i++) {
            if (Pattern.compile("[a-z]").matcher(c[i] + "").find()) {
                if ((c[i + 1] == c[i] + 1) && (c[i + 2] == c[i] + 2)) {
                    j++;
                }
            }
        }
        score += -3 * j;
        return -3 * j;
    }

    //��������123 234֮�೬��3���۷�
    public int seriesNum2Three() {
        int j = 0;
        char[] c = this.password.toLowerCase(Locale.CHINA).toCharArray();
        for (int i = 0; i < c.length - 2; i++) {
            if (Pattern.compile("[0-9]").matcher(c[i] + "").find()) {
                if ((c[i + 1] == c[i] + 1) && (c[i + 2] == c[i] + 2)) {
                    j++;
                }
            }
        }
        score += -3 * j;
        return -3 * j;
    }

    public void ExtraPoints() {
        System.out.println("�ܴa�֔�=" + CheckpasswordLength());
        System.out.println("��Ӣ����Ԫ=" + CheckpasswordUpper());
        System.out.println("С��Ӣ����Ԫ=" + CheckPwsLower());
        System.out.println("������Ԫ=" + checkNum());
        System.out.println("��̖��Ԫ=" + checkChar());
        System.out.println("�ܴa���g���唵�ֻ��̖��Ԫ=" + checkNumOrCharInStr());
        System.out.println("���_�ܴa���Ҫ���Ŀ=" + LowerQuest());
    }

    public void MinusPoint() {
        System.out.println("ֻ��Ӣ����Ԫ=" + OnlyHasAlp());
        System.out.println("ֻ�Д�����Ԫ=" + OnlyHasNum());
        System.out.println("���}��Ԫ (Case Insensitive)=" + repeatDex());
        System.out.println("�B�mӢ�Ĵ���Ԫ=" + seriseUpperAlp());
        System.out.println("�B�mӢ��С����Ԫ=" + seriseLowerAlp());
        System.out.println("�B�m������Ԫ=" + seriseNum());
        System.out.println("�B�m��ĸ���^����(��abc,def)=" + seriesAlp2Three());
        System.out.println("�B�m���ֳ��^����(��123,234)=" + seriesNum2Three());
    }

    public static void main(String[] args) {
        CheckPassword checkPassword = new CheckPassword("g7CA9HgI!cn*QcAM");
    }
}